package pl.szpadel.android.gadu.packets;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

import pl.szpadel.android.gadu.AGLog;

/** Package header */
public class Header {
	
	private static final String TAG = "Header";
	
	// we need two buffer, because reading and writing happens concurrently in different threads
	// Actually, the proper solution would be to use thread-local storage
	private static ByteBuffer mReadBuffer = ByteBuffer.allocateDirect(8);
	private static ByteBuffer mWriteBuffer = ByteBuffer.allocateDirect(8);
	
	private int mType = 0; /// package type
	private int mLength = 0; /// package length
	
	public int getType() {
		return mType;
	}
	
	public int getLength() {
		return mLength;
	}
	
	/// Private constructor. Only way to cnostruct this is to use static method
	public Header(int type, int len) {
		mType = type;
		mLength = len;
	}
	
	/// Creates header from input channel
	static public Header createFromChannel(ReadableByteChannel channel) throws IOException {
		mReadBuffer.clear();
		while(mReadBuffer.position() < 8){
			int r = channel.read(mReadBuffer);
			if  (r < 0){
				throw new IOException("Channel closed while reading header");
			} else if (r == 0){
				throw new IOException("Header: channel has no data!!!! read so far:" + mReadBuffer.position());
			}
		}
		AGLog.d(TAG, "reading finished");
		
		mReadBuffer.flip();
		mReadBuffer.order(ByteOrder.LITTLE_ENDIAN);

		return new Header(mReadBuffer.getInt(), mReadBuffer.getInt());
	}
	
	/// Wrties to channel
	public void toChannel(WritableByteChannel channel) throws IOException {
		mWriteBuffer.clear();
		mWriteBuffer.order(ByteOrder.LITTLE_ENDIAN);

		mWriteBuffer.putInt(mType);
		mWriteBuffer.putInt(mLength);
		mWriteBuffer.flip();
	
		channel.write(mWriteBuffer);
	}

	/// TO string
	public String toString() {
		return "Header [type=0x" + Integer.toHexString(mType) + ", len=" + mLength + " ]";
	}
	
}
